﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: TwoSampleProportionTest.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2012-09-06 11:39 AM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using BOL.Maths.Distributions;

namespace BOL.Maths.Statistics.HypothesisTest
{
    public sealed class TwoSampleProportionTest : TwoSampleTestBase<bool>
    {
        #region Private variables

        private readonly int _numberOfSuccess1;
        private readonly int _numberOfSuccess2;

        #endregion

        #region Constructors

        public TwoSampleProportionTest(TestType type, double alpha, double p12, int sampleSize1, int numberOfSuccess1, int sampleSize2, int numberOfSuccess2)
            : base(type, alpha, p12, 
            Enumerable.Repeat(true, numberOfSuccess1).Concat(Enumerable.Repeat(false, sampleSize1 - numberOfSuccess1)), 
            Enumerable.Repeat(true, numberOfSuccess2).Concat(Enumerable.Repeat(false, sampleSize2 - numberOfSuccess2)))
        {
            _numberOfSuccess1 = numberOfSuccess1;
            _numberOfSuccess2 = numberOfSuccess2;

            Distribution = new GaussianDistribution();
        }

        public TwoSampleProportionTest(TestType type, double p12, int sampleSize1, int numberOfSuccess1, int sampleSize2, int numberOfSuccess2) : this(type, 0.05, p12, sampleSize1, numberOfSuccess1, sampleSize2, numberOfSuccess2) { }

        public TwoSampleProportionTest(double alpha, double p12, int sampleSize1, int numberOfSuccess1, int sampleSize2, int numberOfSuccess2) : this(TestType.TwoSided, alpha, p12, sampleSize1, numberOfSuccess1, sampleSize2, numberOfSuccess2) { }

        public TwoSampleProportionTest(double p12, int sampleSize1, int numberOfSuccess1, int sampleSize2, int numberOfSuccess2) : this(TestType.TwoSided, 0.05, p12, sampleSize1, numberOfSuccess1, sampleSize2, numberOfSuccess2) { }

        public TwoSampleProportionTest(TestType type, double alpha, double p12, IEnumerable<bool> sample1, IEnumerable<bool> sample2)
            : base(type, alpha, p12, sample1, sample2)
        {
            _numberOfSuccess1 = Sample1.Count(x => x);
            _numberOfSuccess2 = Sample2.Count(x => x);

            Distribution = new GaussianDistribution();
        }

        public TwoSampleProportionTest(TestType type, double p12, IEnumerable<bool> sample1, IEnumerable<bool> sample2) : this(type, 0.05, p12, sample1, sample2) { }

        public TwoSampleProportionTest(double alpha, double p12, IEnumerable<bool> sample1, IEnumerable<bool> sample2) : this(TestType.TwoSided, alpha, p12, sample1, sample2) { }

        public TwoSampleProportionTest(double p12, IEnumerable<bool> sample1, IEnumerable<bool> sample2) : this(TestType.TwoSided, 0.05, p12, sample1, sample2) { }

        #endregion

        #region Protected methods

        protected override double PointEstimate()
        {
            return _numberOfSuccess1 / (double)SampleSize1 - _numberOfSuccess2 / (double)SampleSize2;
        }

        protected override double PointEstimateStandardError()
        {
            var pi1 = _numberOfSuccess1 / (double)SampleSize1;
            var pi2 = _numberOfSuccess2 / (double)SampleSize2;
            var proportionStdError1 = Math.Sqrt(pi1 * (1 - pi1) / SampleSize1);
            var proportionStdError2 = Math.Sqrt(pi2 * (1 - pi2) / SampleSize2);

            return Math.Sqrt(Math.Pow(proportionStdError1, 2) + Math.Pow(proportionStdError2, 2));
        }

        #endregion
    }
}
